
/*
 * MainGUI.java
 *
 * Created on Feb 27, 2011, 10:24:33 PM
 */

package jsat.guitool;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.*;
import java.util.List;
import javax.swing.*;
import jsat.*;
import jsat.classifiers.ClassificationDataSet;
import jsat.classifiers.Classifier;
import jsat.clustering.OPTICS;
import jsat.datatransform.*;
import jsat.distributions.*;
import jsat.distributions.empirical.KernelDensityEstimator;
import jsat.distributions.empirical.kernelfunc.GaussKF;
import jsat.graphing.*;
import jsat.linear.DenseVector;
import jsat.linear.Vec;
import jsat.math.Function;
import jsat.math.SimpleLinearRegression;
import jsat.parameters.Parameterized;
import jsat.testing.goodnessoffit.KSTest;
import jsat.testing.onesample.TTest;
import jsat.testing.onesample.ZTest;
import jsat.utils.ProbailityMatch;

/**
 *
 * @author Edwarf Raff
 */
public class MainGUI extends javax.swing.JFrame
{
    Distribution[] distributions = new Distribution[] 
    { 
        new Normal(), new LogNormal(), new Exponential(), new ChiSquared(10), 
        new Gamma(2, 1), new FisherSendor(10, 10), new Weibull(2, 1), 
        new Uniform(0, 1)
    };
    
    SimpleDataSet data;
    DataTransformProcess dtp;

    /** Creates new form MainGUI */
    public MainGUI()
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e)
        {
            System.out.println("Error setting native LAF: " + e);
        }
        dtp = new DataTransformProcess();
        initComponents();
        jMenuItemHisto.setEnabled(false);
        jMenuItemQQData.setEnabled(false);
        jMenuItemQQDist.setEnabled(false);
        jMenuItemScatter.setEnabled(false);
        jMenuItemScatterMatrix.setEnabled(false);
        jMenuItemSingleVariable.setEnabled(false);
        setSize(400, 300);
    }
    
    private ClassificationDataSet getClassificationData()
    {
        if(jMenuPredictingClass.getItemCount() == 0)
            return null;
        int selected = -1;
        for(int i =0; i < jMenuPredictingClass.getItemCount(); i++)
        {
            JRadioButtonMenuItem button = (JRadioButtonMenuItem) jMenuPredictingClass.getItem(i);
            if(button.isSelected())
            {
                selected = i;
                break;
            }
        }
        
        
        ClassificationDataSet cds = new ClassificationDataSet(data.getBackingList(), selected);
        for(int i = 0; i < data.getNumNumericalVars(); i++)
            cds.setNumericName(data.getNumericName(i), i);
        return cds;
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents()
    {

        jfc = new javax.swing.JFileChooser();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenuFile = new javax.swing.JMenu();
        jMenuItemOpen = new javax.swing.JMenuItem();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        jMenuVisualize = new javax.swing.JMenu();
        jMenuItemPCA = new javax.swing.JMenuItem();
        jMenuItemWhitePCA = new javax.swing.JMenuItem();
        jMenuItemParaCoords = new javax.swing.JMenuItem();
        jMenuItemReachabilityPlot = new javax.swing.JMenuItem();
        jMenuItemHisto = new javax.swing.JMenuItem();
        jMenuItemKDE = new javax.swing.JMenuItem();
        jMenuItemScatter = new javax.swing.JMenuItem();
        jMenuItemScatterMatrix = new javax.swing.JMenuItem();
        jMenuItemQQDist = new javax.swing.JMenuItem();
        jMenuItemQQData = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenu4 = new javax.swing.JMenu();
        jMenu5 = new javax.swing.JMenu();
        jMenuKSSearch = new javax.swing.JMenuItem();
        jMenu6 = new javax.swing.JMenu();
        jMenuItemOneSampZ = new javax.swing.JMenuItem();
        jMenuItemOneSamT = new javax.swing.JMenuItem();
        jMenuItemSingleVariable = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItemLinearRegress = new javax.swing.JMenuItem();
        jMenuClassification = new javax.swing.JMenu();
        jMenuPredictingClass = new javax.swing.JMenu();
        jMenuCVisualize = new javax.swing.JMenu();
        jMenuClassPCA = new javax.swing.JMenuItem();
        jMenuClassWhitePCA = new javax.swing.JMenuItem();
        jMenuItemClassParaCoords = new javax.swing.JMenuItem();
        jMenuCrossValidateTest = new javax.swing.JMenuItem();
        jMenuTransform = new javax.swing.JMenu();
        jMenuCurTransforms = new javax.swing.JMenu();
        jItemClearTransforms = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jItemTransUnitVariance = new javax.swing.JMenuItem();
        jItemTransZeroMean = new javax.swing.JMenuItem();
        jItemTransPCA = new javax.swing.JMenuItem();
        jItemTransWhitenedPCA = new javax.swing.JMenuItem();
        jItemTransWhitenedZCA = new javax.swing.JMenuItem();
        jItemTransPolynomial = new javax.swing.JMenuItem();
        jItemTransLinear = new javax.swing.JMenuItem();
        jMenuItemNumericHistro = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.GridLayout(1, 1));

        jMenuFile.setText("File");

        jMenuItemOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItemOpen.setText("Open");
        jMenuItemOpen.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemOpenActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItemOpen);

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setText("Exit");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenuFile.add(jMenuItem1);

        jMenuBar1.add(jMenuFile);

        jMenu1.setText("View");

        jMenuVisualize.setText("Visualize");

        jMenuItemPCA.setText("PCA");
        jMenuItemPCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemPCAActionPerformed(evt);
            }
        });
        jMenuVisualize.add(jMenuItemPCA);

        jMenuItemWhitePCA.setText("Whitened PCA");
        jMenuItemWhitePCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemWhitePCAActionPerformed(evt);
            }
        });
        jMenuVisualize.add(jMenuItemWhitePCA);

        jMenuItemParaCoords.setText("Parallel Corrdinates");
        jMenuItemParaCoords.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemParaCoordsActionPerformed(evt);
            }
        });
        jMenuVisualize.add(jMenuItemParaCoords);

        jMenuItemReachabilityPlot.setText("Reachability Plot");
        jMenuItemReachabilityPlot.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemReachabilityPlotActionPerformed(evt);
            }
        });
        jMenuVisualize.add(jMenuItemReachabilityPlot);

        jMenu1.add(jMenuVisualize);

        jMenuItemHisto.setText("Histogram");
        jMenuItemHisto.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemHistoActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemHisto);

        jMenuItemKDE.setText("KDE Estimate");
        jMenuItemKDE.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemKDEActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemKDE);

        jMenuItemScatter.setText("Scatter Plot");
        jMenuItemScatter.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemScatterActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemScatter);

        jMenuItemScatterMatrix.setText("Scatter Matrix");
        jMenuItemScatterMatrix.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemScatterMatrixActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemScatterMatrix);

        jMenuItemQQDist.setText("QQ Plot Distribution");
        jMenuItemQQDist.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemQQDistActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemQQDist);

        jMenuItemQQData.setText("QQ Plot Data");
        jMenuItemQQData.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemQQDataActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItemQQData);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Statistics");

        jMenu4.setText("Tests");

        jMenu5.setText("Goodness of Fit");

        jMenuKSSearch.setText(" Kolmogorov Search");
        jMenuKSSearch.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuKSSearchActionPerformed(evt);
            }
        });
        jMenu5.add(jMenuKSSearch);

        jMenu4.add(jMenu5);

        jMenu6.setText("One Sample");

        jMenuItemOneSampZ.setText("Z-Test");
        jMenuItemOneSampZ.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemOneSampZActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItemOneSampZ);

        jMenuItemOneSamT.setText("T-Test");
        jMenuItemOneSamT.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemOneSamTActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItemOneSamT);

        jMenu4.add(jMenu6);

        jMenu2.add(jMenu4);

        jMenuItemSingleVariable.setText("Single Variable");
        jMenuItemSingleVariable.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemSingleVariableActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItemSingleVariable);

        jMenuBar1.add(jMenu2);

        jMenu3.setText("Regression");

        jMenuItemLinearRegress.setText("Linear");
        jMenuItemLinearRegress.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemLinearRegressActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItemLinearRegress);

        jMenuBar1.add(jMenu3);

        jMenuClassification.setText("Classification");

        jMenuPredictingClass.setText("Predicting");
        jMenuClassification.add(jMenuPredictingClass);

        jMenuCVisualize.setText("Visualize");

        jMenuClassPCA.setText("PCA");
        jMenuClassPCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuClassPCAActionPerformed(evt);
            }
        });
        jMenuCVisualize.add(jMenuClassPCA);

        jMenuClassWhitePCA.setText("Whitened PCA");
        jMenuClassWhitePCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuClassWhitePCAActionPerformed(evt);
            }
        });
        jMenuCVisualize.add(jMenuClassWhitePCA);

        jMenuItemClassParaCoords.setText("Parallel Coordinates");
        jMenuItemClassParaCoords.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemClassParaCoordsActionPerformed(evt);
            }
        });
        jMenuCVisualize.add(jMenuItemClassParaCoords);

        jMenuClassification.add(jMenuCVisualize);

        jMenuCrossValidateTest.setText("Cross Validate");
        jMenuCrossValidateTest.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuCrossValidateTestActionPerformed(evt);
            }
        });
        jMenuClassification.add(jMenuCrossValidateTest);

        jMenuBar1.add(jMenuClassification);

        jMenuTransform.setText("Transform");

        jMenuCurTransforms.setText("Current Transforms");
        jMenuTransform.add(jMenuCurTransforms);

        jItemClearTransforms.setText("Clear Transforms");
        jItemClearTransforms.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemClearTransformsActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemClearTransforms);
        jMenuTransform.add(jSeparator1);

        jItemTransUnitVariance.setText("Unit Variance");
        jItemTransUnitVariance.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransUnitVarianceActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransUnitVariance);

        jItemTransZeroMean.setText("Zero Mean");
        jItemTransZeroMean.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransZeroMeanActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransZeroMean);

        jItemTransPCA.setText("PCA");
        jItemTransPCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransPCAActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransPCA);

        jItemTransWhitenedPCA.setText("Whitened PCA");
        jItemTransWhitenedPCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransWhitenedPCAActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransWhitenedPCA);

        jItemTransWhitenedZCA.setText("Whitened ZCA");
        jItemTransWhitenedZCA.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransWhitenedZCAActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransWhitenedZCA);

        jItemTransPolynomial.setText("Polynomial");
        jItemTransPolynomial.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransPolynomialActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransPolynomial);

        jItemTransLinear.setText("Linear");
        jItemTransLinear.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jItemTransLinearActionPerformed(evt);
            }
        });
        jMenuTransform.add(jItemTransLinear);

        jMenuItemNumericHistro.setText("Numeric to Histogram");
        jMenuItemNumericHistro.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jMenuItemNumericHistroActionPerformed(evt);
            }
        });
        jMenuTransform.add(jMenuItemNumericHistro);

        jMenuBar1.add(jMenuTransform);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItemOpenActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemOpenActionPerformed
    {//GEN-HEADEREND:event_jMenuItemOpenActionPerformed
        int retVal = jfc.showOpenDialog(this);

        if(retVal == JFileChooser.APPROVE_OPTION)
        {
            File file = jfc.getSelectedFile();
            try
            {
                data = ARFFLoader.loadArffFile(file);

                VecTableModel vt = new VecTableModel(data);
                JTable jt  = new JTable(vt);
                getContentPane().removeAll();
                getContentPane().add(new JScrollPane(jt));
                //Set up option selection for the classification job
                updateMenuPreductingClassItems();
                validate();
                jMenuItemHisto.setEnabled(true);
                jMenuItemQQData.setEnabled(true);
                jMenuItemQQDist.setEnabled(true);
                jMenuItemScatter.setEnabled(true);
                jMenuItemScatterMatrix.setEnabled(true);
                jMenuItemSingleVariable.setEnabled(true);
            }
            catch (Exception ex)
            {

            }
        }
    }//GEN-LAST:event_jMenuItemOpenActionPerformed

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem1ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem1ActionPerformed
        System.exit(0);
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jMenuItemScatterActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemScatterActionPerformed
    {//GEN-HEADEREND:event_jMenuItemScatterActionPerformed
        if(data == null || data.getNumNumericalVars() < 2)
        {
            JOptionPane.showMessageDialog(null, "You need at least 2 sets of data for a scatter plot", "Scatter Plot error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        DataSetSelection dss = new DataSetSelection(null, "Select X and Y Axis", data, new String[]{"X axis", "Y axis"});
        int[] axie =  dss.getSelections();

        
        ScatterPlot sp = new ScatterPlot(data.getNumericColumn(axie[0]), data.getNumericColumn(axie[1]));

        sp.setXAxisTtile(data.getNumericName(axie[0]));
        sp.setYAxisTtile(data.getNumericName(axie[1]));

        GraphDialog gd = new GraphDialog(null, "Sactter Plot of " + data.getNumericName(axie[0]) + " & " + data.getNumericName(axie[1]), sp);

        gd.setSize(300, 300);
        gd.setVisible(true);
        

    }//GEN-LAST:event_jMenuItemScatterActionPerformed

    private void jMenuItemQQDistActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemQQDistActionPerformed
    {//GEN-HEADEREND:event_jMenuItemQQDistActionPerformed
        DataSetSelection dss = new DataSetSelection(null, "Select data to check", data, new String[]{"QQ Plot Data"});

        int[] axie =  dss.getSelections();

        //Pre set the distributions to have paramaters assuming that they match the data
        for (int i = 0; i < distributions.length; i++)
            try
            {
                distributions[i].setUsingData(data.getNumericColumn(axie[0]));
            }
            catch (Exception ex)
            {
                //Its okay for a distribution to be unabel to fit
            }

        DistributionSelectionDialog dsd = new DistributionSelectionDialog(null, "Select distribution to compare against", distributions);
        
        Distribution dist = dsd.getDistribution();

        QQPlotDistribution qq = new QQPlotDistribution(dist, data.getNumericColumn(axie[0]));

        qq.setYAxisTtile(data.getNumericName(axie[0]));
        GraphDialog gd = new GraphDialog(null, "QQ Plot of " +  data.getNumericName(axie[0]) , qq);


        gd.setSize(300, 300);
        gd.setVisible(true);
    }//GEN-LAST:event_jMenuItemQQDistActionPerformed

    private void jMenuItemQQDataActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemQQDataActionPerformed
    {//GEN-HEADEREND:event_jMenuItemQQDataActionPerformed
        DataSetSelection dss = new DataSetSelection(null, "Select data to check", data, new String[]{"X Axis", "Y Axis"});
        int[] axie =  dss.getSelections();

        QQPlotData qq = new QQPlotData(data.getNumericColumn(axie[1]), data.getNumericColumn(axie[0]));

        qq.setXAxisTtile(data.getNumericName(axie[0]));
        qq.setYAxisTtile(data.getNumericName(axie[1]));

        GraphDialog gd = new GraphDialog(null, "QQ Plot of " + data.getNumericName(axie[0]) + " & " + data.getNumericName(axie[1]), qq);

        gd.setSize(300, 300);
        gd.setVisible(true);
    }//GEN-LAST:event_jMenuItemQQDataActionPerformed

    private void jMenuItemSingleVariableActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemSingleVariableActionPerformed
    {//GEN-HEADEREND:event_jMenuItemSingleVariableActionPerformed
        SingleVariableViewDialog svvd = new SingleVariableViewDialog(data);
        svvd.pack();
        svvd.setVisible(true);
    }//GEN-LAST:event_jMenuItemSingleVariableActionPerformed

    private void jMenuItemScatterMatrixActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemScatterMatrixActionPerformed
    {//GEN-HEADEREND:event_jMenuItemScatterMatrixActionPerformed
        ScatterplotMatrix sm = new ScatterplotMatrix(null, "Scatter Matrix", data);

        sm.setSize(600, 600);
        sm.setVisible(true);
    }//GEN-LAST:event_jMenuItemScatterMatrixActionPerformed

    private void jMenuItemHistoActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemHistoActionPerformed
    {//GEN-HEADEREND:event_jMenuItemHistoActionPerformed
        DataSetSelection dss = new DataSetSelection(null, "Select data to create histogram from", data, new String[]{"Histogram Data"});
        int[] axie =  dss.getSelections();

        Histogram hh = new Histogram(data.getNumericColumn(axie[0]));

        hh.setXAxisTtile(data.getNumericName(axie[0]));

        GraphDialog gd = new GraphDialog(null, "Histogram of " + data.getNumericName(axie[0]), hh);

        gd.setSize(300, 300);
        gd.setVisible(true);
    }//GEN-LAST:event_jMenuItemHistoActionPerformed

    private void jMenuItemLinearRegressActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemLinearRegressActionPerformed
    {//GEN-HEADEREND:event_jMenuItemLinearRegressActionPerformed
        if(data.getNumNumericalVars() < 2)
        {
            JOptionPane.showMessageDialog(null, "You need at least 2 sets of data for Linear Regression", "Linear Regression error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        DataSetSelection dss = new DataSetSelection(null, "Select data to perform Linear Regression on", data, new String[]{"Y data", "X data"});
        int[] axie =  dss.getSelections();

        final double[] ab = SimpleLinearRegression.regres(data.getNumericColumn(axie[1]), data.getNumericColumn(axie[0]));
        
        Function linearFunc = new Function() {

            public double f(double... x)
            {
                return ab[0] + ab[1]*x[0];
            }

            public double f(Vec x)
            {
                return f(x.get(0));
            }
        };

        ScatterPlot sp = new ScatterPlot(data.getNumericColumn(axie[1]), data.getNumericColumn(axie[0]));

        sp.setRegressionFunction(linearFunc);
        sp.setXAxisTtile(data.getNumericName(axie[1]));
        sp.setYAxisTtile(data.getNumericName(axie[0]));

        
        GraphDialog gd = new GraphDialog(null, "y = " + ab[0] + " + " + ab[1] + 
                "x, Linear Regression of " + data.getNumericName(axie[0]) + 
                " & " + data.getNumericName(axie[1]), sp);

        gd.setSize(300, 300);
        gd.setVisible(true);


    }//GEN-LAST:event_jMenuItemLinearRegressActionPerformed

    private void jMenuKSSearchActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuKSSearchActionPerformed
    {//GEN-HEADEREND:event_jMenuKSSearchActionPerformed
        DataSetSelection dss = new DataSetSelection(null, "Select data to attempt to detect the distribution of",
                data, new String[]{"Data Set"});
        
        
        int[] axie = dss.getSelections();
        for (int i = 0; i < distributions.length; i++)
            try
            {
                distributions[i].setUsingData(data.getNumericColumn(axie[0]));
            }
            catch (RuntimeException ex)
            {
            }
        
        KSTest ks = new KSTest(data.getNumericColumn(axie[0])) ;
        List<ProbailityMatch<Distribution>> pValues = 
                new ArrayList<ProbailityMatch<Distribution>>(distributions.length);
        
        for (int i = 0; i < distributions.length; i++)
        {
            try
            {
                double p = ks.testDist(distributions[i]);
                if(p >= 0.05)
                    pValues.add(new ProbailityMatch<Distribution>(p, distributions[i]));
            }
            catch(ArithmeticException ex)
            {
                
            }
        }
        
        Collections.sort(pValues);
        Collections.reverse(pValues); 
        
        
        String[] possible = new String[pValues.size()];
        for(int i = 0; i < pValues.size(); i++)
            possible[i] = pValues.get(i).getMatch().getDescriptiveName();
        
        
        JList jl = new JList(possible);

        JFrame jf = new JFrame("Possiible Distribution matches for " + data.getNumericName(axie[0]));
        if(possible.length > 0)
        {
            JPanel jp = new JPanel(new GridLayout(1, 1));
            jp.add(new JScrollPane(jl));
            jf.setContentPane(jp);
        }
        else//No distribution match
        {
            JPanel jp = new JPanel(new GridLayout(1, 1));
            jp.add(new JLabel("No known distribution seems to match this data set"));
            jf.setContentPane(jp);
        }
        jf.setVisible(true);
        jf.pack();
        
    }//GEN-LAST:event_jMenuKSSearchActionPerformed

    private void jMenuItemOneSampZActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemOneSampZActionPerformed
    {//GEN-HEADEREND:event_jMenuItemOneSampZActionPerformed
        OneSampleTestDialog dia = new OneSampleTestDialog(new ZTest(), data);
        
        dia.setSize(300, 300);
        dia.setVisible(true);
    }//GEN-LAST:event_jMenuItemOneSampZActionPerformed

    private void jMenuItemOneSamTActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemOneSamTActionPerformed
    {//GEN-HEADEREND:event_jMenuItemOneSamTActionPerformed
        OneSampleTestDialog dia = new OneSampleTestDialog(new TTest(), data);
        
        dia.setSize(300, 300);
        dia.setVisible(true);
    }//GEN-LAST:event_jMenuItemOneSamTActionPerformed

    private void jMenuClassPCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuClassPCAActionPerformed
    {//GEN-HEADEREND:event_jMenuClassPCAActionPerformed
        ClassificationDataSet cds = getClassificationData();
        if(cds == null)
            JOptionPane.showMessageDialog(rootPane, "This data set has no categorical attributes to use as a class",
                    "Can not perform class visualization", JOptionPane.ERROR_MESSAGE);
        else if(cds.getNumNumericalVars() < 2)
            JOptionPane.showMessageDialog(rootPane, "This data set does not have enough numerical attributes to plot",
                    "Can not perform class visualization", JOptionPane.ERROR_MESSAGE);
        else
        {
            cds.applyTransform(new ZeroMeanTransform(cds));
            cds.applyTransform(new PCA(cds, 2));
            GraphDialog dialog = new GraphDialog(null, "PCA Visualization", new CategoryPlot(cds));
            dialog.setSize(400, 400);
            dialog.setVisible(true);
        }
    }//GEN-LAST:event_jMenuClassPCAActionPerformed

    private void jMenuCrossValidateTestActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuCrossValidateTestActionPerformed
    {//GEN-HEADEREND:event_jMenuCrossValidateTestActionPerformed
        ClassifierSelectionDialog csd = new ClassifierSelectionDialog(getClassificationData(), this);
        csd.pack();
        csd.setVisible(true);
        
        if(csd.isCanceled())
            return;
        List<Classifier> classifiers = csd.getSelectedClassifiers();
        List<String> classifierNames = csd.getSelectedNames();
        if(classifiers.isEmpty())
            return;
        ClassifierCVEvaluation eval = new ClassifierCVEvaluation(classifiers, 
                classifierNames, getClassificationData(), this, "Title", false, 
                dtp);
        
        
    }//GEN-LAST:event_jMenuCrossValidateTestActionPerformed

    private void jMenuItemClassParaCoordsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemClassParaCoordsActionPerformed
    {//GEN-HEADEREND:event_jMenuItemClassParaCoordsActionPerformed
        ClassificationDataSet cds = getClassificationData();
        if(cds == null)
            JOptionPane.showMessageDialog(rootPane, "This data set has no categorical attributes to use as a class",
                    "Can not perform class visualization", JOptionPane.ERROR_MESSAGE);
        else
        {
            GraphDialog dialog = new GraphDialog(null, "Parallel Coordinates", new ParallelCoordinatesPlot(cds));
            dialog.setSize(400, 400);
            dialog.setVisible(true);
        }
    }//GEN-LAST:event_jMenuItemClassParaCoordsActionPerformed

    private void jMenuItemKDEActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemKDEActionPerformed
    {//GEN-HEADEREND:event_jMenuItemKDEActionPerformed
        DataSetSelection dss = new DataSetSelection(null, "Select data to create KDE from", data, new String[]{"KDE Data"});
        int[] axie =  dss.getSelections();

        Vec dataVec = data.getNumericColumn(axie[0]);
        final KernelDensityEstimator kde = new KernelDensityEstimator(dataVec, GaussKF.getInstance());
        
        double shift = kde.getBandwith()*2;
        final Graph2D hh = new Graph2D(dataVec.min()-shift, dataVec.max()+shift, 0, kde.pdf(kde.mode())*1.1)
        {

            @Override
            protected void paintWork(Graphics g, int imageWidth, int imageHeight, ProgressPanel pp)
            {
                super.paintWork(g, imageWidth, imageHeight, pp);
                g.setColor(Color.BLUE);
                drawFunction((Graphics2D)g, Distribution.getFunctionPDF(kde));
            }
            
        };
        

        hh.setXAxisTtile(data.getNumericName(axie[0]));

        GraphDialog gd = new GraphDialog(null, "KDE Estimation of " + data.getNumericName(axie[0]), hh);

        gd.setSize(300, 300);
        gd.setVisible(true);
    }//GEN-LAST:event_jMenuItemKDEActionPerformed

    private void jMenuItemReachabilityPlotActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemReachabilityPlotActionPerformed
    {//GEN-HEADEREND:event_jMenuItemReachabilityPlotActionPerformed
        
        final JDialog waitDialog = new JDialog(this, "Compuring", true);
        
        final ProgressPanel pp = new ProgressPanel("Computing OPTICS", "Reachability Plot will be taken from OPTICS");
        waitDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        waitDialog.setContentPane(pp);
        waitDialog.pack();
        
        final MainGUI gui = this;
        
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run()
            {
                final OPTICS optics = new OPTICS();
                optics.cluster(data);

                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run()
                    {
                        ReachabilityPlot plot = new ReachabilityPlot(optics.getReachabilityArray());
                        JDialog jdialog = new JDialog(gui, "Reachability Plot");
                        jdialog.setContentPane(new JScrollPane(plot));
                        jdialog.setSize(plot.getPreferredSize());
                        jdialog.setVisible(true);
                        waitDialog.setVisible(false);
                    }
                });
            }
        });
        
        thread.start();
        waitDialog.setVisible(true);
        
    }//GEN-LAST:event_jMenuItemReachabilityPlotActionPerformed

    private void jMenuItemParaCoordsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemParaCoordsActionPerformed
    {//GEN-HEADEREND:event_jMenuItemParaCoordsActionPerformed
        GraphDialog dialog = new GraphDialog(null, "Parallel Coordinates", new ParallelCoordinatesPlot(data));
        dialog.setSize(400, 400);
        dialog.setVisible(true);
    }//GEN-LAST:event_jMenuItemParaCoordsActionPerformed

    private void jMenuClassWhitePCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuClassWhitePCAActionPerformed
    {//GEN-HEADEREND:event_jMenuClassWhitePCAActionPerformed
        ClassificationDataSet cds = getClassificationData();
        if(cds == null)
            JOptionPane.showMessageDialog(rootPane, "This data set has no categorical attributes to use as a class",
                    "Can not perform class visualization", JOptionPane.ERROR_MESSAGE);
        else if(cds.getNumNumericalVars() < 2)
            JOptionPane.showMessageDialog(rootPane, "This data set does not have enough numerical attributes to plot",
                    "Can not perform class visualization", JOptionPane.ERROR_MESSAGE);
        else
        {
            cds.applyTransform(new ZeroMeanTransform(cds));
            cds.applyTransform(new WhitenedPCA(cds, 2));
            GraphDialog dialog = new GraphDialog(null, "whitened PCA Visualization", new CategoryPlot(cds));
            dialog.setSize(400, 400);
            dialog.setVisible(true);
        }
    }//GEN-LAST:event_jMenuClassWhitePCAActionPerformed

    private void jMenuItemWhitePCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemWhitePCAActionPerformed
    {//GEN-HEADEREND:event_jMenuItemWhitePCAActionPerformed
        SimpleDataSet sds = new SimpleDataSet(data.getDataPoints());
        if(sds == null)
            JOptionPane.showMessageDialog(rootPane, "This data set has no categorical attributes to use as a class",
                    "Can not perform visualization", JOptionPane.ERROR_MESSAGE);
        else if(sds.getNumNumericalVars() < 2)
            JOptionPane.showMessageDialog(rootPane, "This data set does not have enough numerical attributes to plot",
                    "Can not perform visualization", JOptionPane.ERROR_MESSAGE);
        else
        {
            sds.applyTransform(new ZeroMeanTransform(sds));
            sds.applyTransform(new WhitenedPCA(sds, 2));
            GraphDialog dialog = new GraphDialog(null, "whitened PCA Visualization", new ScatterPlot(sds.getNumericColumn(0), sds.getNumericColumn(1)));
            dialog.setSize(400, 400);
            dialog.setVisible(true);
        }
    }//GEN-LAST:event_jMenuItemWhitePCAActionPerformed

    private void jMenuItemPCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemPCAActionPerformed
    {//GEN-HEADEREND:event_jMenuItemPCAActionPerformed
        SimpleDataSet sds = new SimpleDataSet(data.getDataPoints());
        if(sds == null)
            JOptionPane.showMessageDialog(rootPane, "This data set has no categorical attributes to use as a class",
                    "Can not perform visualization", JOptionPane.ERROR_MESSAGE);
        else if(sds.getNumNumericalVars() < 2)
            JOptionPane.showMessageDialog(rootPane, "This data set does not have enough numerical attributes to plot",
                    "Can not perform visualization", JOptionPane.ERROR_MESSAGE);
        else
        {
            sds.applyTransform(new ZeroMeanTransform(sds));
            sds.applyTransform(new PCA(sds, 2));
            GraphDialog dialog = new GraphDialog(null, "PCA Visualization", new ScatterPlot(sds.getNumericColumn(0), sds.getNumericColumn(1)));
            dialog.setSize(400, 400);
            dialog.setVisible(true);
        }
    }//GEN-LAST:event_jMenuItemPCAActionPerformed

    private void jItemTransPolynomialActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransPolynomialActionPerformed
    {//GEN-HEADEREND:event_jItemTransPolynomialActionPerformed
        String s = JOptionPane.showInputDialog(rootPane, "Please Specify the degree for the transform", "Polynomial Transform", JOptionPane.QUESTION_MESSAGE);
        
        try
        {
            int degree = Integer.parseInt(s);
            if(degree < 1)
                throw new RuntimeException();
            dtp.addTransform(new PolynomialTransform.PolyTransformFactory(degree));
            jMenuCurTransforms.add(new JLabel(" Polynomial of degree "+degree+" "));
        }
        catch(Exception ex)
        {
            //TODO show error
        }
    }//GEN-LAST:event_jItemTransPolynomialActionPerformed

    private void jItemTransUnitVarianceActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransUnitVarianceActionPerformed
    {//GEN-HEADEREND:event_jItemTransUnitVarianceActionPerformed
        dtp.addTransform(new UnitVarianceTransform.UnitVarianceTransformFactory());
        jMenuCurTransforms.add(new JLabel(" Unit Variance "));
    }//GEN-LAST:event_jItemTransUnitVarianceActionPerformed

    private void jItemTransZeroMeanActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransZeroMeanActionPerformed
    {//GEN-HEADEREND:event_jItemTransZeroMeanActionPerformed
        dtp.addTransform(new ZeroMeanTransform.ZeroMeanTransformFactory());
        jMenuCurTransforms.add(new JLabel(" Zero Mean "));
    }//GEN-LAST:event_jItemTransZeroMeanActionPerformed

    private void jItemTransPCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransPCAActionPerformed
    {//GEN-HEADEREND:event_jItemTransPCAActionPerformed
        String s = JOptionPane.showInputDialog(rootPane, "Please Specify the number of components for the transform", "PCA Transform", JOptionPane.QUESTION_MESSAGE);
        
        try
        {
            int pcs = Integer.parseInt(s);
            if(pcs < 1)
                throw new RuntimeException();
            dtp.addTransform(new PCA.PCAFactory(pcs));
            jMenuCurTransforms.add(new JLabel(" PCA ["+pcs+"] "));
        }
        catch(Exception ex)
        {
            //TODO show error
        }
    }//GEN-LAST:event_jItemTransPCAActionPerformed

    private void jItemTransWhitenedPCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransWhitenedPCAActionPerformed
    {//GEN-HEADEREND:event_jItemTransWhitenedPCAActionPerformed
        String s = JOptionPane.showInputDialog(rootPane, "Please Specify the number of components for the transform", "Whitened PCA Transform", JOptionPane.QUESTION_MESSAGE);
        
        try
        {
            int pcs = Integer.parseInt(s);
            if(pcs < 1)
                throw new RuntimeException();
            dtp.addTransform(new WhitenedPCA.WhitenedPCATransformFactory(pcs));
            jMenuCurTransforms.add(new JLabel(" Whitened PCA ["+ pcs+ "] "));
        }
        catch(Exception ex)
        {
            //TODO show error
        }
    }//GEN-LAST:event_jItemTransWhitenedPCAActionPerformed

    private void jItemTransWhitenedZCAActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransWhitenedZCAActionPerformed
    {//GEN-HEADEREND:event_jItemTransWhitenedZCAActionPerformed

        dtp.addTransform(new WhitenedZCA.WhitenedZCATransformFactory());
        jMenuCurTransforms.add(new JLabel(" Whitened ZCA "));
    }//GEN-LAST:event_jItemTransWhitenedZCAActionPerformed

    private void jItemTransLinearActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemTransLinearActionPerformed
    {//GEN-HEADEREND:event_jItemTransLinearActionPerformed
        String s = JOptionPane.showInputDialog(rootPane, 
            "Please specify the minimum and maximum range for the transform as "
                + "\"min,max\" ", "Linear Transform", JOptionPane.QUESTION_MESSAGE);
        
        try
        {
            String[] split = s.split(",");
            if(split.length != 2)
                throw new RuntimeException();
            double B = Double.parseDouble(split[0]);
            double A = Double.parseDouble(split[1]);
            dtp.addTransform(new LinearTransform.LinearTransformFactory(A, B));
            jMenuCurTransforms.add(new JLabel(" Linear ["+A+", "+B+"] "));
        }
        catch(Exception ex)
        {
            //TODO show error
        }
    }//GEN-LAST:event_jItemTransLinearActionPerformed

    private void jItemClearTransformsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jItemClearTransformsActionPerformed
    {//GEN-HEADEREND:event_jItemClearTransformsActionPerformed
        dtp = new DataTransformProcess();
        jMenuCurTransforms.removeAll();
    }//GEN-LAST:event_jItemClearTransformsActionPerformed

    private void jMenuItemNumericHistroActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemNumericHistroActionPerformed
    {//GEN-HEADEREND:event_jMenuItemNumericHistroActionPerformed
        dtp.addTransform(new NumericalToHistogram.NumericalToHistogramTransformFactory());
        jMenuCurTransforms.add(new JLabel("Numerical to Histogram"));
    }//GEN-LAST:event_jMenuItemNumericHistroActionPerformed

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainGUI().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem jItemClearTransforms;
    private javax.swing.JMenuItem jItemTransLinear;
    private javax.swing.JMenuItem jItemTransPCA;
    private javax.swing.JMenuItem jItemTransPolynomial;
    private javax.swing.JMenuItem jItemTransUnitVariance;
    private javax.swing.JMenuItem jItemTransWhitenedPCA;
    private javax.swing.JMenuItem jItemTransWhitenedZCA;
    private javax.swing.JMenuItem jItemTransZeroMean;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenu jMenu5;
    private javax.swing.JMenu jMenu6;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenu jMenuCVisualize;
    private javax.swing.JMenuItem jMenuClassPCA;
    private javax.swing.JMenuItem jMenuClassWhitePCA;
    private javax.swing.JMenu jMenuClassification;
    private javax.swing.JMenuItem jMenuCrossValidateTest;
    private javax.swing.JMenu jMenuCurTransforms;
    private javax.swing.JMenu jMenuFile;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItemClassParaCoords;
    private javax.swing.JMenuItem jMenuItemHisto;
    private javax.swing.JMenuItem jMenuItemKDE;
    private javax.swing.JMenuItem jMenuItemLinearRegress;
    private javax.swing.JMenuItem jMenuItemNumericHistro;
    private javax.swing.JMenuItem jMenuItemOneSamT;
    private javax.swing.JMenuItem jMenuItemOneSampZ;
    private javax.swing.JMenuItem jMenuItemOpen;
    private javax.swing.JMenuItem jMenuItemPCA;
    private javax.swing.JMenuItem jMenuItemParaCoords;
    private javax.swing.JMenuItem jMenuItemQQData;
    private javax.swing.JMenuItem jMenuItemQQDist;
    private javax.swing.JMenuItem jMenuItemReachabilityPlot;
    private javax.swing.JMenuItem jMenuItemScatter;
    private javax.swing.JMenuItem jMenuItemScatterMatrix;
    private javax.swing.JMenuItem jMenuItemSingleVariable;
    private javax.swing.JMenuItem jMenuItemWhitePCA;
    private javax.swing.JMenuItem jMenuKSSearch;
    private javax.swing.JMenu jMenuPredictingClass;
    private javax.swing.JMenu jMenuTransform;
    private javax.swing.JMenu jMenuVisualize;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JFileChooser jfc;
    // End of variables declaration//GEN-END:variables

    /**
     * Empties out the contents of {@link #jMenuPredictingClass} and then re populates is accordingly. 
     */
    private void updateMenuPreductingClassItems()
    {
        jMenuPredictingClass.removeAll();
        if (data.getNumCategoricalVars() > 0)
        {
            List<JRadioButtonMenuItem> classSelectionOptions = new ArrayList<JRadioButtonMenuItem>(data.getNumCategoricalVars());
            for (int i = 0; i < data.getNumCategoricalVars(); i++)
            {
                JRadioButtonMenuItem classButtonOption = new JRadioButtonMenuItem(data.getCategoryName(i));
                classButtonOption.setSelected(false);
                classSelectionOptions.add(classButtonOption);
            }

            ButtonGroup buttonGroup = new ButtonGroup();
            for (JRadioButtonMenuItem jrbmi : classSelectionOptions)
                buttonGroup.add(jrbmi);
            classSelectionOptions.get(classSelectionOptions.size() - 1).setSelected(true);

            for (JRadioButtonMenuItem jrbmi : classSelectionOptions)
                jMenuPredictingClass.add(jrbmi);
        }
    }

}
